home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / SOX.ARJ / WAV.C < prev   
C/C++ Source or Header  |  1992-06-15  |  4KB  |  193 lines

  1. /*
  2.  * April 15, 1992
  3.  * Copyright 1992 Rick Richardson
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Windows 3.0 .wav format driver
  13.  */
  14.  
  15. #include "st.h"
  16.  
  17. /* Private data for .wav file */
  18. typedef struct wavstuff {
  19.     long    samples;
  20. } *wav_t;
  21.  
  22. extern float volume, amplitude;
  23. extern long summary, verbose;
  24.  
  25. /*
  26.  * Do anything required before you start reading samples.
  27.  * Read file header. 
  28.  *    Find out sampling rate, 
  29.  *    size and style of samples, 
  30.  *    mono/stereo/quad.
  31.  */
  32. wavstartread(ft) 
  33. ft_t ft;
  34. {
  35.     wav_t    wav = (wav_t) ft->priv;
  36.     char    magic[4];
  37.     long    len;
  38.  
  39.     /* If you need to seek around the input file. */
  40.     if (0 && ! ft->seekable)
  41.         fail(".wav input file must be a file, not a pipe");
  42.  
  43.     fread(magic, 4, 1, ft->fp);
  44.     if (strncmp("RIFF", magic, 4))
  45.         fail("Not a RIFF file");
  46.  
  47.     len = rllong(ft);
  48.  
  49.     fread(magic, 4, 1, ft->fp);
  50.     if (strncmp("WAVE", magic, 4))
  51.         fail("Not a WAVE file");
  52.  
  53.     fread(magic, 4, 1, ft->fp);
  54.     if (strncmp("fmt ", magic, 4))
  55.         fail("Missing fmt spec");
  56.  
  57.     len = rllong(ft);
  58.     switch (rlshort(ft))
  59.     {
  60.     case 1:        ft->info.style = UNSIGNED; break;
  61.     default:    fail("Don't understand format");
  62.     }
  63.     ft->info.channels = rlshort(ft);
  64.     ft->info.rate = rllong(ft);
  65.     rllong(ft);    /* Average bytes/second */
  66.     rlshort(ft);    /* Block align */
  67.     switch (rlshort(ft))
  68.     {
  69.     case 8:        ft->info.size = BYTE; break;
  70.     case 16:    ft->info.size = WORD; break;
  71.     case 32:    ft->info.size = LONG; break;
  72.     default:    fail("Don't understand size");
  73.     }
  74.     len -= 16;
  75.     while (len) getc(ft->fp);
  76.  
  77.     fread(magic, 4, 1, ft->fp);
  78.     if (strncmp("data", magic, 4))
  79.         fail("Missing data portion");
  80.  
  81.     wav->samples = rllong(ft);
  82. }
  83.  
  84. /*
  85.  * Read up to len samples from file.
  86.  * Convert to signed longs.
  87.  * Place in buf[].
  88.  * Return number of samples read.
  89.  */
  90.  
  91. wavread(ft, buf, len) 
  92. ft_t ft;
  93. long *buf, len;
  94. {
  95.     wav_t    wav = (wav_t) ft->priv;
  96.     int    done;
  97.  
  98.     if (len > wav->samples) len = wav->samples;
  99.     if (len == 0) return 0;
  100.     done = rawread(ft, buf, len);
  101.     wav->samples -= len;
  102.     return done;
  103. }
  104.  
  105. /*
  106.  * Do anything required when you stop reading samples.  
  107.  * Don't close input file! 
  108.  */
  109. wavstopread(ft) 
  110. ft_t ft;
  111. {
  112. }
  113.  
  114. wavstartwrite(ft) 
  115. ft_t ft;
  116. {
  117.     wav_t    wav = (wav_t) ft->priv;
  118.     int    littlendian = 0;
  119.     char    *endptr;
  120.  
  121.     if (! ft->seekable)
  122.         fail("Output .wav file must be a file, not a pipe");
  123.  
  124.     endptr = (char *) &littlendian;
  125.     *endptr = 1;
  126.     if (!littlendian) ft->swap = 1;
  127.  
  128.     wav->samples = 0;
  129.     wavwritehdr(ft);
  130. }
  131.  
  132. wavwritehdr(ft) 
  133. ft_t ft;
  134. {
  135.     wav_t    wav = (wav_t) ft->priv;
  136.     int    samsize;
  137.     long    datasize;
  138.  
  139.     switch (ft->info.size)
  140.     {
  141.     case BYTE:    samsize = 8; break;
  142.     case WORD:    samsize = 16; break;
  143.     default:
  144.     case LONG:    ft->info.size = LONG; samsize = 32; break;
  145.     }
  146.     ft->info.style = UNSIGNED;
  147.  
  148.     datasize = samsize/8 * ft->info.channels * wav->samples;
  149.  
  150.     fputs("RIFF", ft->fp);
  151.     wllong(ft, datasize + 8+16+12);    /* Waveform chunk size: FIXUP(4) */
  152.     fputs("WAVE", ft->fp);
  153.     fputs("fmt ", ft->fp);
  154.     wllong(ft, (long)16);        /* fmt chunk size */
  155.     wlshort(ft, 1);            /* FormatTag: WAVE_FORMAT_PCM */
  156.     wlshort(ft, ft->info.channels);
  157.     wllong(ft, (long)ft->info.rate);    /* SamplesPerSec */
  158.                     /* Average Bytes/sec */
  159.     wllong(ft, (long)(ft->info.rate * ft->info.channels * samsize + 7) / 8);
  160.                     /* nBlockAlign */
  161.     wlshort(ft, (ft->info.channels * samsize + 7) / 8);
  162.     wlshort(ft, samsize);        /* BitsPerSample */
  163.     
  164.     fputs("data", ft->fp);
  165.     wllong(ft, datasize);        /* data chunk size: FIXUP(40) */
  166. }
  167.  
  168. wavwrite(ft, buf, len) 
  169. ft_t ft;
  170. long *buf, len;
  171. {
  172.     wav_t    wav = (wav_t) ft->priv;
  173.  
  174.     wav->samples += len * ft->info.size;
  175.     rawwrite(ft, buf, len);
  176. }
  177.  
  178. void
  179. wavstopwrite(ft) 
  180. ft_t ft;
  181. {
  182.     /* All samples are already written out. */
  183.     /* If file header needs fixing up, for example it needs the */
  184.      /* the number of samples in a field, seek back and write them here. */
  185.     wav_t    wav = (wav_t) ft->priv;
  186.  
  187.     if (!ft->seekable)
  188.         return;
  189.     if (fseek(ft->fp, 0L, 0) != 0)
  190.         fail("Can't rewind output file to rewrite .wav header.");
  191.     wavwritehdr(ft);
  192. }
  193.